
using System;
using System.Threading;
using System.IO;

using Anculus.Core;

using Galaxium.Core;
using Galaxium.Client;

using Galaxium.Protocol.Xmpp.Library;

namespace Galaxium.Protocol.Xmpp
{
	public class XmppFileTransfer: AbstractFileTransfer
	{
		private Library.Streams.FileTransfer _transfer;
		private string _name = null;
		
		public XmppFileTransfer (XmppSession session, Library.Streams.FileTransfer transfer)
			:base (session, session.GetContact (transfer.EntityUID), 
			       transfer.Target == null, transfer.FileName)
		{
			_transfer = transfer;
			
		//	if (!base.Incoming)
		//		transfer.Offer ();
			
			base.TotalBytes = transfer.FileSize;
			
			_transfer.Initiated += HandleInitiated;
			_transfer.Failed += HandleFailed;
			_transfer.Finished += HandleFinished;
			_transfer.Rejected += HandleRejected;
			
			var thr = new Thread (() => {
				while (base.State == TransferState.Pending ||
				       base.State == TransferState.Started ||
				       base.State == TransferState.Progressing) {
					
					if (TransferedBytes != _transfer.Transferred) {
						TransferedBytes = _transfer.Transferred;
						ThreadUtility.Dispatch (() => OnTransferProgress (new FileTransferEventArgs (this)));
					}
					
					Thread.Sleep (200);
				}
			});
			thr.IsBackground = true;
			thr.Start ();
		}

		void HandleRejected(object sender, TextEventArgs e)
		{
			ThreadUtility.Dispatch (() => OnTransferDecline (new FileTransferEventArgs (this)));
		}

		void HandleFinished(object sender, EventArgs e)
		{
			TransferedBytes = _transfer.Transferred;
			ThreadUtility.Dispatch (() => OnTransferProgress (new FileTransferEventArgs (this)));
			ThreadUtility.Dispatch (() => OnTransferFinish (new FileTransferEventArgs (this)));
		}

		void HandleFailed(object sender, TextEventArgs e)
		{
			ThreadUtility.Dispatch (() => OnTransferFailed (new FileTransferErrorEventArgs (this, e.Text)));
		}

		void HandleInitiated (object sender, EventArgs e)
		{
			base._startTime = DateTime.Now; 
			base.TransferedBytes = 0;
			ThreadUtility.Dispatch (() => OnTransferStart (new FileTransferEventArgs (this)));
		}
		
		public override void Rename (string filename)
		{
			_name = filename;
		}

		public void Offer ()
		{
			_transfer.Offer ();
		}
		
		public override void Accept ()
		{
			_transfer.FilePath = Path.Combine (FileTransferUtility.DestinationFolder,
			                                   _name ?? _transfer.FileName);
			_transfer.Accept ();
			OnTransferStart (new FileTransferEventArgs (this));
		}

		public override void Decline ()
		{
			_transfer.Decline (null);
			OnTransferDecline (new FileTransferEventArgs (this));
		}

		public override void Abort ()
		{
			_transfer.Abort ();
			OnTransferLocalAbort (new FileTransferEventArgs (this));
		}
	}
}
